package api

import (
	"gitee.com/liuxiaowei123/vblog-01/vblog-01/vblog/blog"
	"gitee.com/liuxiaowei123/vblog-01/vblog-01/vblog/middlewares"
	"gitee.com/liuxiaowei123/vblog-01/vblog-01/vblog/response"
	"gitee.com/liuxiaowei123/vblog-01/vblog-01/vblog/token"
	"gitee.com/liuxiaowei123/vblog-01/vblog-01/vblog/user"
	"github.com/gin-gonic/gin"
)

// 此文件，实现把功能暴漏

// 把apihandler注册到路由上
func (b *BlogApihandler) Registry(r gin.IRouter) {
	// r 是Gin的路由器,所以这里不用gin.Default()
	v1 := r.Group("v1").Group("blogs")
	// 需要公开给访客访问 可以不用做校验、鉴权
	v1.GET("/", b.QueryBlog)
	// GET /api/vblog/v1/blogs/43
	// url路径里面有变量:id, 声明一个路径变量, 通过r.Params("id") 就可以获取到43
	v1.GET("/:id", b.DescribeBlog)

	// 后台管理接口 需要认证，在这里做认证表示后面所有路由都需要认证
	v1.Use(middlewares.NewTokenAuther().Auth)
	// POST /api/vblog/v1/blogs
	// v1.POST("/", b.CreateBlog)
	v1.POST("/", middlewares.Required(user.ROLE_AUTHOR), b.CreateBlog)
	// v1.PUT("/:id", b.UpdatePutBlog)
	v1.PUT("/:id", middlewares.Required(user.ROLE_AUTHOR), b.UpdatePutBlog)
	// v1.PATCH("/:id", b.UpdatePatchBlog)
	v1.PATCH("/:id", middlewares.Required(user.ROLE_AUTHOR), b.UpdatePatchBlog)
	// v1.DELETE("/:id", b.DeleteBlog)
	v1.DELETE("/:id", middlewares.Required(user.ROLE_AUTHOR), b.DeleteBlog)
	// // POST /vblog/api/v1/blogs/43/audit
	// v1.POST("/:id/audit", b.AuditBlog)
	v1.POST("/:id/audit", middlewares.Required(user.ROLE_AUDITOR), b.AuditBlog)

}

// 以下是apihandler实现注册到路由中的方法
// 下面的方法中，上下文参数，都要用c.Request.Context()

func (b *BlogApihandler) CreateBlog(c *gin.Context) {

	// 使用请求上下文，获取数据
	contexttk := c.Keys[token.TOKEN_GIN_KEY_NAME]
	// 错误代码：tk := contexttk.(token.Token)
	tk := contexttk.(*token.Token)

	// 1.从http server获取请求的数据
	req := blog.NewCreateBlogRequest()
	err := c.BindJSON(req)
	if err != nil {
		response.Failed(c, err)
		// return语句的作用是终止当前处理程序的执行并返回给调用者,如果不加上return语句，将会继续执行后续的处理程序
		// return
	}

	// 在获取的上下文中补充内容（用cookie中携带的Token信息来补充）
	// 通过获取上下文中的token，知道登录用户
	req.CreateBy = tk.UserName

	// 2.处理请求
	ins, err := b.blogsvc.CreateBlog(c.Request.Context(), req)
	if err != nil {
		response.Failed(c, err)
	}
	// 3.返回响应
	response.Success(c, ins)
}

// GET /vblog/api/v1/blogs/?page_size=1&page_number=20
func (b *BlogApihandler) QueryBlog(c *gin.Context) {
	// 1. 用户请求；从url中获取数据GET /vblog/api/v1/blogs/?page_size=1&page_number=20
	req := blog.NewQueryBlogRequest()
	// 把获取的字符串转为整型
	// strconv.ParseInt(c.Query("page_number"), 10, 64)
	// strconv.ParseInt(c.Query("page_size"), 10, 64)
	// 改进，通过QueryBlogRequest的方法扩展
	req.Keywords = c.Query("keywords")
	req.ParsePageNumber(c.Query("page_number"))
	req.ParsePageSize(c.Query("page_size"))
	switch c.Query("status") {
	case "draft":
		// 错误代码：req.Status = blog.STATUS_DRAFT
		req.SetStatus(blog.STATUS_DRAFT)
	case "published":
		req.SetStatus(blog.STATUS_PUBLISHED)
	}

	// 2.处理请求
	ins, err := b.blogsvc.QueryBlog(c.Request.Context(), req)
	if err != nil {
		response.Failed(c, err)
	}
	// 3.返回响应
	response.Success(c, ins)
}

// v1.GET("/:id", b.DescribeBlog)
// GET /vblog/api/v1/blogs/43
func (b *BlogApihandler) DescribeBlog(c *gin.Context) {
	// 1. 用户请求
	// 因为定义的是v1.GET("/:id", h.DescribeBlog)，所以用c.Param("id")
	req := blog.NewDescribeBlogRequest(c.Param("id"))
	// 2.处理请求
	ins, err := b.blogsvc.DescribeBlog(c.Request.Context(), req)
	if err != nil {
		response.Failed(c, err)
	}
	// 3.返回响应
	response.Success(c, ins)
}

// 全量更新
func (b *BlogApihandler) UpdatePutBlog(c *gin.Context) {
	// 1. 用户请求
	/*blog.NewUpdatePUTBlogRequest(c.Param("id"))创建一个新的请求对象，该对象包含从HTTP请求中获取的"id"参数。
	然后，c.BindJSON(req.CreateBlogRequest) 将请求正文解析为 JSON 数据并绑定到该请求对象中*/
	req := blog.NewUpdatePUTBlogRequest(c.Param("id"))
	err := c.BindJSON(req.CreateBlogRequest)
	if err != nil {
		response.Failed(c, err)
	}
	// 2.处理请求
	ins, err := b.blogsvc.UpdateBlog(c.Request.Context(), req)
	if err != nil {
		response.Failed(c, err)
	}
	// 3.返回响应
	response.Success(c, ins)
}

func (b *BlogApihandler) UpdatePatchBlog(c *gin.Context) {
	// 1. 用户请求
	req := blog.NewUpdatePATCHBlogRequest(c.Param("id"))
	err := c.BindJSON(req.CreateBlogRequest)
	if err != nil {
		response.Failed(c, err)
	}
	// 2.处理请求
	ins, err := b.blogsvc.UpdateBlog(c.Request.Context(), req)
	if err != nil {
		response.Failed(c, err)
	}
	// 3.返回响应
	response.Success(c, ins)
}

func (b *BlogApihandler) DeleteBlog(c *gin.Context) {
	// 1. 用户请求
	req := blog.NewDeleteBlogRequest(c.Param("id"))
	// 2.处理请求
	err := b.blogsvc.DeleteBlog(c.Request.Context(), req)
	if err != nil {
		response.Failed(c, err)
	}
	// 3.返回响应
	response.Success(c, "OK")
}

func (b *BlogApihandler) AuditBlog(c *gin.Context) {
	req := blog.NewAuditBlogRequest(c.Param("id"))
	err := c.BindJSON(req)
	if err != nil {
		response.Failed(c, err)
	}

	// 注意AuditBlog参数中的上下文，不是c,而是c.Request.Context()
	ins, err := b.blogsvc.AuditBlog(c.Request.Context(), req)
	if err != nil {
		response.Failed(c, err)
	}

	response.Success(c, ins)
}
